package redora.performance.runners;

import redora.exceptions.RedoraException;
import redora.impl.DatabaseFactory;
import redora.performance.PerformanceTest;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Random;

/**
 * Runs the benchmark using pure JDBC, in batch mode where possible. It will do
 * a few dummy getXxx to make it more realistic
 */
public class JDBCRunner {

    public static long[] run(int count) throws RedoraException, SQLException {
        long[] ret = { 99999999999999L, 99999999999999999L, 9999999999999999L, 9999999999999999L,
                0L, 0L };

        PerformanceTest.prepare();
        Connection con = DatabaseFactory.connection().con;

        ret[0] = insert(con, count);
        ret[1] = retrieve(con);
        ret[2] = perObject(con, count);
        ret[3] = update(con);

        return ret;
    }

    private static long insert(Connection con, int count) throws SQLException {

        PreparedStatement ps = con
                .prepareStatement("insert into Tweet (smallText, number, creationDate) values (?, ?, now())");
        long start = System.nanoTime();

        for (int i = 0; i < count; i++) {
            ps.setString(1, "company");
            ps.setInt(2, new Random(i).nextInt());
            ps.addBatch();
        }
        ps.executeBatch();

        return Math.abs(System.nanoTime() - start);
    }

    private static long retrieve(Connection con) throws SQLException {
        long start = System.nanoTime();

        PreparedStatement ps = con
                .prepareStatement("select id, smallText, number, creationDate, updateDate from Tweet");
        ResultSet r = ps.executeQuery();
        while (r.next()) {
            if (!r.getString(2).equals("error")) {
                r.getLong(1);
                r.getInt(3);
                r.getDate(4);
                r.getDate(5);
            }
        }

        return Math.abs(System.nanoTime() - start);
    }

    private static long perObject(Connection con, int count) throws SQLException {
        insert(con, count);
        PreparedStatement ps = con
                .prepareStatement("select id, smallText, number, creationDate, updateDate from Tweet where id = ?");

        long start = System.nanoTime();

        for (int i = 1; i < count; i++) {
            ps.setInt(1, i);
            ResultSet r = ps.executeQuery();
            r.next();

            r.getLong(1);
            r.getString(2);
            r.getInt(3);
            r.getDate(4);
            r.getDate(5);
        }
        return Math.abs(System.nanoTime() - start);
    }

    private static long update(Connection con) throws SQLException {
        PreparedStatement ps = con
                .prepareStatement("select id, smallText, number, creationDate, updateDate from Tweet");
        ResultSet r = ps.executeQuery();

        long start = System.nanoTime();
        PreparedStatement psInsert = con
                .prepareStatement("update Tweet set smallText=?, number=?, updateDate=now() where id=?");
        while (r.next()) {
            if (!r.getString(2).equals("error")) {
                psInsert.setLong(3, r.getLong(1));
                psInsert.setString(1, "new company");
                psInsert.setInt(2, new Random().nextInt());
                psInsert.addBatch();
            }
        }
        psInsert.executeBatch();
        return Math.abs(System.nanoTime() - start);
    }
}
